package com.xbts.system.service.impl;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.huaweicloud.sdk.bss.v2.BssClient;
import com.huaweicloud.sdk.bss.v2.model.*;
import com.huaweicloud.sdk.bss.v2.region.BssRegion;
import com.huaweicloud.sdk.core.auth.BasicCredentials;
import com.huaweicloud.sdk.core.auth.GlobalCredentials;
import com.huaweicloud.sdk.core.auth.ICredential;
import com.huaweicloud.sdk.core.exception.ConnectionException;
import com.huaweicloud.sdk.core.exception.RequestTimeoutException;
import com.huaweicloud.sdk.core.exception.ServiceResponseException;
import com.huaweicloud.sdk.ecs.v2.EcsClient;
import com.huaweicloud.sdk.ecs.v2.model.*;
import com.huaweicloud.sdk.ecs.v2.region.EcsRegion;
import com.huaweicloud.sdk.eip.v2.EipClient;
import com.huaweicloud.sdk.eip.v2.model.ListPublicipsRequest;
import com.huaweicloud.sdk.eip.v2.model.ListPublicipsResponse;
import com.huaweicloud.sdk.eip.v2.model.PublicipShowResp;
import com.huaweicloud.sdk.eip.v2.region.EipRegion;
import com.huaweicloud.sdk.iam.v3.IamClient;
import com.huaweicloud.sdk.iam.v3.model.*;
import com.huaweicloud.sdk.iam.v3.region.IamRegion;
import com.huaweicloud.sdk.ims.v2.ImsClient;
import com.huaweicloud.sdk.ims.v2.model.CreateImageResponse;
import com.huaweicloud.sdk.ims.v2.model.ListImagesResponse;
import com.huaweicloud.sdk.ims.v2.region.ImsRegion;
import com.huaweicloud.sdk.vpc.v2.VpcClient;
import com.huaweicloud.sdk.vpc.v2.model.*;
import com.huaweicloud.sdk.vpc.v2.region.VpcRegion;
import com.xbts.common.constant.Constants;
import com.xbts.common.core.domain.AjaxResult;
import com.xbts.common.core.domain.entity.SysUser;
import com.xbts.common.core.domain.model.LoginUser;
import com.xbts.common.core.redis.RedisCache;
import com.xbts.common.enums.HttpMethod;
import com.xbts.common.enums.ServerStatusEnum;
import com.xbts.common.enums.SettingEnum;
import com.xbts.common.enums.ShoppingCarEnums;
import com.xbts.common.exception.ServiceException;
import com.xbts.common.utils.DateUtils;
import com.xbts.common.utils.SecurityUtils;
import com.xbts.common.utils.SnowFlakeUtil;
import com.xbts.common.utils.StringUtils;
import com.xbts.common.utils.http.HttpUtils;
import com.xbts.system.domain.*;
import com.xbts.system.domain.dto.*;
import com.xbts.system.enums.OrderStatusEnum;
import com.xbts.system.enums.OrderTypeEnum;
import com.xbts.system.mapper.SysUserMapper;
import com.xbts.system.module.payment.enums.PaymentMethodEnum;
import com.xbts.system.module.payment.service.ICnWalletLogService;
import com.xbts.system.service.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpEntity;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.io.IOException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Service
@Slf4j
public class HuaweiAccountServiceImpl implements IHuaweiAccountService {

    private final String USER_TO_HUAWEI = "USER_TO_HUAWEI";

    @Autowired
    private SettingService settingService;

    @Autowired
    private RedisCache redisCache;

    @Autowired
    private ICnHuaweiAccountBindInfoService cnHuaweiAccountBindInfoService;

    @Override
    public synchronized AjaxResult createSubCustomer(RegionIdDTO<CreateSubCustomerRequest> dto) {
        Map<String, Object> cacheMapOld = (Map<String, Object>) redisCache.getCacheObject(USER_TO_HUAWEI);
        if(StringUtils.isNotNull(cacheMapOld)){
            throw new ServiceException("系统繁忙，请稍后再试!");
        }

        BssClient client = getBssClient(dto.getRegionId());
        CreateSubCustomerRequest request = dto.getBody();
        CreateCustomerV2Req body = request.getBody();

        String domainName = body.getDomainName();

        // 校验参数是否合法
        if(StringUtils.isNotBlank(domainName)) {
            RegionIdDTO<CheckUserIdentityRequest> checkUserIdentityDto = new RegionIdDTO<>();
            CheckUserIdentityRequest checkUserIdentityRequest = new CheckUserIdentityRequest();
            checkUserIdentityDto.setBody(checkUserIdentityRequest);
            CheckSubcustomerUserReq checkSubcustomerUserReq = new CheckSubcustomerUserReq();
            checkSubcustomerUserReq.setSearchType("name");
            checkSubcustomerUserReq.setSearchValue(domainName);
            checkUserIdentityRequest.setBody(checkSubcustomerUserReq);
            AjaxResult ajaxResult = checkUserIdentity(checkUserIdentityDto);
            if ((int) ajaxResult.get("code") != 200) {
                return ajaxResult;
            }
        }

        // 中酒云平台用户唯一标识
        body.setXaccountId(SecurityUtils.getUserId().toString());
        // 获取合作伙伴平台唯一标识
        String xaccountType = getXAccountType();
        body.setXaccountType(xaccountType);
        // 是否返回子客户的关联结果。
        body.setIncludeAssociationResult(true);
        // 设置二级经销商ID
        String indirectPartnerId = getIndirectPartnerId();
        body.setIndirectPartnerId(indirectPartnerId);
        try {
            CreateSubCustomerResponse response = client.createSubCustomer(request);
            System.out.println(response.toString());

            // 判断是否创建成功
            if(response.getHttpStatusCode() != 200){
                return AjaxResult.error("创建失败，请稍后再试！");
            }
            // 创建成功后续处理
            CnHuaweiAccountBindInfo cnHuaweiAccountBindInfo = new CnHuaweiAccountBindInfo();
            cnHuaweiAccountBindInfo.setDomainId(response.getDomainId());
            cnHuaweiAccountBindInfo.setDomainName(response.getDomainName());
            cnHuaweiAccountBindInfo.setMobilePhone(body.getMobilePhone());
            cnHuaweiAccountBindInfo.setXaccountId(body.getXaccountId());
            cnHuaweiAccountBindInfo.setPassword(body.getPassword());
            cnHuaweiAccountBindInfo.setStatus("1");
            cnHuaweiAccountBindInfo.setIndirectPartnerId(body.getIndirectPartnerId());
            cnHuaweiAccountBindInfo.setIsCloseMarketMs(body.getIsCloseMarketMs());
            cnHuaweiAccountBindInfoService.save(cnHuaweiAccountBindInfo);

            HashMap<String, Object> cacheMap = new HashMap<>();
            cacheMap.put("xAccountId", cnHuaweiAccountBindInfo.getXaccountId());
            cacheMap.put("domain_id", cnHuaweiAccountBindInfo.getDomainId());
            cacheMap.put("idp_id", getXAccountType());
            redisCache.setCacheObject(USER_TO_HUAWEI, cacheMap, 5, TimeUnit.SECONDS);

            return AjaxResult.success();
        } catch (ConnectionException | RequestTimeoutException e) {
            e.printStackTrace();
        } catch (ServiceResponseException e) {
            e.printStackTrace();
            System.out.println(e.getHttpStatusCode());
            System.out.println(e.getRequestId());
            System.out.println(e.getErrorCode());
            System.out.println(e.getErrorMsg());
        }
        return null;
    }

    @Override
    public AjaxResult checkUserIdentity(RegionIdDTO<CheckUserIdentityRequest> dto) {
        BssClient client = getBssClient(dto.getRegionId());
        CheckUserIdentityRequest request = dto.getBody();
        try {
            CheckUserIdentityResponse response = client.checkUserIdentity(request);
            System.out.println(response.toString());
            String checkResult = response.getCheckResult();
            if(StringUtils.equals("available",checkResult)){
                return AjaxResult.success();
            }else if(StringUtils.equals("used_by_user",checkResult)){
                AjaxResult error = AjaxResult.error("该登录名称/手机号/邮箱已被占用。");
                return error;
            }
        } catch (ConnectionException e) {
            e.printStackTrace();
        } catch (RequestTimeoutException e) {
            e.printStackTrace();
        } catch (ServiceResponseException e) {
            e.printStackTrace();
            System.out.println(e.getHttpStatusCode());
            System.out.println(e.getRequestId());
            System.out.println(e.getErrorCode());
            System.out.println(e.getErrorMsg());
        }
        return AjaxResult.error("校验失败！请稍后再试。");
    }

    @Override
    public AjaxResult sendVerificationMessageCode(RegionIdDTO<SendVerificationMessageCodeRequest> dto) {
        BssClient client = getBssClient(dto.getRegionId());
        SendVerificationMessageCodeRequest request = dto.getBody();
        SendVerificationCodeV2Req body = request.getBody();
        body.setReceiverType(1);
        body.setTimeout(10);
        body.setScene(29);
        body.setLang("zh-cn");
        try {
            SendVerificationMessageCodeResponse response = client.sendVerificationMessageCode(request);
            System.out.println(response.toString());
        } catch (ConnectionException | RequestTimeoutException e) {
            e.printStackTrace();
        } catch (ServiceResponseException e) {
            e.printStackTrace();
            System.out.println(e.getHttpStatusCode());
            System.out.println(e.getRequestId());
            System.out.println(e.getErrorCode());
            System.out.println(e.getErrorMsg());
        }
        return null;
    }

    @Override
    public AjaxResult listIndirectPartners(RegionIdDTO<ListIndirectPartnersRequest> dto) {
        BssClient client = getBssClient(dto.getRegionId());
        ListIndirectPartnersRequest request = dto.getBody();
        try {
            ListIndirectPartnersResponse response = client.listIndirectPartners(request);
            System.out.println(response.toString());
            return AjaxResult.success(response);
        } catch (ConnectionException | RequestTimeoutException e) {
            e.printStackTrace();
        } catch (ServiceResponseException e) {
            e.printStackTrace();
            System.out.println(e.getHttpStatusCode());
            System.out.println(e.getRequestId());
            System.out.println(e.getErrorCode());
            System.out.println(e.getErrorMsg());
        }
        return null;
    }

    @Override
    public AjaxResult listSubCustomers(RegionIdDTO<ListSubCustomersRequest> dto) {
        BssClient client = getBssClient(dto.getRegionId());
        ListSubCustomersRequest request = dto.getBody();
        try {
            ListSubCustomersResponse response = client.listSubCustomers(request);
            System.out.println(response.toString());
            return AjaxResult.success(response);
        } catch (ConnectionException | RequestTimeoutException e) {
            e.printStackTrace();
        } catch (ServiceResponseException e) {
            e.printStackTrace();
            System.out.println(e.getHttpStatusCode());
            System.out.println(e.getRequestId());
            System.out.println(e.getErrorCode());
            System.out.println(e.getErrorMsg());
        }
        return null;
    }

    @Override
    public AjaxResult accountBind(HuaweiAccountBindDTO dto) {
        log.info("~~~~~~~~~~~~~华为云账号绑定通知。");
        log.info("~~~~~~~~~~~~~华为云账号绑定通知DTO。{}", dto);

        // 创建成功后续处理
        CnHuaweiAccountBindInfo cnHuaweiAccountBindInfo = new CnHuaweiAccountBindInfo();
//        cnHuaweiAccountBindInfo.setDomainId(response.getDomainId());
//        cnHuaweiAccountBindInfo.setDomainName(response.getDomainName());
//        cnHuaweiAccountBindInfo.setMobilePhone(body.getMobilePhone());
//        cnHuaweiAccountBindInfo.setXaccountId(body.getXaccountId());
//        cnHuaweiAccountBindInfo.setPassword(body.getPassword());
//        cnHuaweiAccountBindInfo.setStatus("1");
//        cnHuaweiAccountBindInfo.setIndirectPartnerId(body.getIndirectPartnerId());
//        cnHuaweiAccountBindInfo.setIsCloseMarketMs(body.getIsCloseMarketMs());
//        cnHuaweiAccountBindInfoService.save(cnHuaweiAccountBindInfo);
        return null;
    }

    @Override
    public synchronized AjaxResult loginParameters() {

        Map<String, Object> cacheMapOld = (Map<String, Object>) redisCache.getCacheObject(USER_TO_HUAWEI);
        if(StringUtils.isNotNull(cacheMapOld)){
            throw new ServiceException("系统繁忙，请稍后再试!");
        }
        // 检查用户是否登录
        Long userId;
        try {
            userId = SecurityUtils.getUserId();
        }catch (Exception e) {
            throw new ServiceException("请先登录!");
        }

        Map<String, Object> map = new HashMap<>();
        // 获取xAccountType
        String xAccountType = getXAccountType();
        map.put("xAccountType", xAccountType);

        // 判断当前用户是否已绑定华为账号
        CnHuaweiAccountBindInfo bindInfo = cnHuaweiAccountBindInfoService.getOne(new LambdaQueryWrapper<CnHuaweiAccountBindInfo>()
                .eq(CnHuaweiAccountBindInfo::getXaccountId, userId));
        map.put("isFirstLogin", StringUtils.isNull(bindInfo));
        if(StringUtils.isNotNull(bindInfo)) {
            HashMap<String, Object> cacheMap = new HashMap<>();
            cacheMap.put("xAccountId", bindInfo.getXaccountId());
            cacheMap.put("domain_id", bindInfo.getDomainId());
            cacheMap.put("idp_id", getXAccountType());
            redisCache.setCacheObject(USER_TO_HUAWEI, cacheMap, 5, TimeUnit.SECONDS);
        }
        return AjaxResult.success(map);
    }


    private String getXAccountType() {
        AccountSetting accountSetting = settingService.getAccountSetting(SettingEnum.HUAWEI_GENERAL_DISTRIBUTOR);
        return accountSetting.getXaccountType();
    }
    private String getIndirectPartnerId() {
        AccountSetting accountSetting = settingService.getAccountSetting(SettingEnum.HUAWEI_GENERAL_DISTRIBUTOR);
        return accountSetting.getIndirectPartnerId();
    }


    private BssClient getBssClient(String regionId) {
        AccountSetting accountSetting = settingService.getAccountSetting(SettingEnum.HUAWEI_GENERAL_DISTRIBUTOR);
        ICredential auth = new GlobalCredentials()
                .withAk(accountSetting.getAccessKeyId())
                .withSk(accountSetting.getSecretAccessKey());

//        regionId = StringUtils.isEmpty(regionId) ? accountSetting.getRegionId() : regionId;
        BssClient client = BssClient.newBuilder()
                .withCredential(auth)
                .withRegion(BssRegion.valueOf("cn-north-1"))
                .build();
        return client;
    }
}
